﻿Imports System.Collections.ObjectModel
Imports System.Reflection
Imports Kairyu.Load

Namespace Save

    ''' <summary>
    ''' テーブルコンテナ生成クラス
    ''' </summary>
    ''' <remarks>
    ''' #107 Storageクラスの見直し
    ''' </remarks>
    Public Class ListArchiveFactory

        ''' <summary>
        ''' テーブルコンテナを生成します
        ''' </summary>
        ''' <param name="instance"></param>
        ''' <param name="t"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function Create(instance As Object, t As Type) As ReadOnlyCollection(Of ListArchive)
            Dim lst As New List(Of ListArchive)

            Dim table As TableAttribute = t.ToTable

            '子クラスのアーカイブ
            '#47Fix 複数列でリレーションする場合、重複しないようにします
            For Each item In (From el In table.ChildRelations Distinct Select el.CollectionProperty Distinct)
                '#69「基底クラスに子プロパティがあるとINSERT文が複数回実行される」 Fix
                '自身がルートである、もしくは、自クラスで実装している子プロパティ以外は処理から除外する
                If table.IsRootBase = False AndAlso item.DeclaringType.Equals(t) = False Then Continue For

                Dim arch As ListArchive = ListArchiveFactory.Create(instance, item)
                If arch Is Nothing Then Continue For
                lst.Add(arch)
            Next

            Return lst.AsReadOnly
        End Function

        ''' <summary>
        ''' テーブルコンテナを生成します
        ''' </summary>
        ''' <param name="instance"></param>
        ''' <param name="prop"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Shared Function Create(instance As Object, prop As PropertyInfo) As ListArchive
            Dim value As ICollection = prop.GetValue(instance, Nothing)
            If value Is Nothing Then
                Return Nothing
            End If

            Dim arch As New ListArchive
            arch.PropertyName = prop.Name

            Dim lst = prop.GetValue(instance, Nothing)
            If TypeOf lst Is ILazy = False OrElse DirectCast(lst, ILazy).IsFetched Then
                For Each item In lst
                    Dim c = TableArchiveFactory.Create(item, item.GetType)
                    arch.TableArchives.Add(c.Key, c)
                Next
            End If

            Return arch
        End Function

    End Class

End Namespace
